import { RegExp } from '~/ui-utils'
import request from '@/utils/request'

// 默认参数
export const defaultParams = [
  {
    key: 'sn',
    name: '货号',
    value: '',
    type: 'String',
    required: true,
    batch: true,
    batchForm: {
      prefix: '',
      step: 1,
      pad_zero: 4,
      initial_value_label: '初始数值'
    }
  },
  {
    key: 'weight',
    name: '重量(kg)',
    value: 0,
    type: 'Number',
    reg: RegExp.money,
    batch: true
  },
  {
    key: 'cost',
    name: '成本价',
    value: 0,
    type: 'Number',
    required: true,
    reg: RegExp.money,
    batch: true
  },
  {
    key: 'price',
    name: '价格',
    value: 0,
    type: 'Number',
    required: true,
    reg: RegExp.money,
    batch: true
  },
  {
    key: 'quantity',
    name: '库存',
    value: 0,
    readonly: true,
    tip: '库存在商品列表单独维护'
  }
]

/**
 * 合并参数
 * @param extendedParams
 */
export const mergeParams = (extendedParams) => {
  let startSort = 10
  defaultParams.forEach(dp => {
    dp.sort = startSort++
  })
  extendedParams.forEach(ep => {
    ep.sort = ep.sort || startSort++
  })
  let params = [...defaultParams]
  extendedParams.forEach(param => {
    const index = params.findIndex(p => p.key === param.key)
    if (index === -1) {
      params.push(cloneJson(param))
    } else {
      params.splice(index, 1, cloneJson(param))
    }
  })
  return params
    .filter(item => item.hidden !== true)
    .map(item => {
      item.max = 99999999
      item.maxlength = 20
      if (item.batch) {
        item.show_batch = false
        item.batchForm = Object.assign({
          prefix: false,
          initial_value: 0,
          initial_value_type: 'Number',
          initial_value_max: 99999999,
          initial_value_maxlength: 20,
          initial_value_label: '批量设置',
          step: false,
          step_max: 99999999,
          pad_zero: false,
          pad_zero_max: 10,
          max: 99999999,
          maxlength: 20
        }, item.batchForm)
      }
      return item
    })
    .sort((x, y) => x.sort - y.sort)
}

/**
 * 获取商品信息
 * @param goods_id
 * @returns {*|Promise<unknown>}
 */
export const getGoodsInfo = (goods_id) => {
  return request({
    url: `/seller/goods/${goods_id}`,
    method: 'get'
  })
}

/**
 * 保存商品SKU信息
 * @param goods_id
 * @param skuLst
 * @returns {*|Promise<unknown>}
 */
export const saveGoodsSkus = (goods_id, skuLst) => {
  return request({
    url: `/seller/goods/${goods_id}/skus`,
    method: 'put',
    needToken: true,
    headers: { 'Content-Type': 'application/json' },
    data: skuLst
  })
}

/**
 * 获取商品SKU信息
 * @param goods_id
 * @returns {*|Promise<unknown>}
 */
export const getGoodsSkus = (goods_id) => {
  return request({
    url: `/seller/goods/${goods_id}/skus`,
    method: 'get',
    loading: false
  })
}

/**
 * 根据分类ID获取规格列表
 * @param category_id
 * @returns {*|Promise<unknown>}
 */
export const getSpecsByCategoryId = (category_id) => {
  return request({
    url: `/seller/goods/categories/${category_id}/specs`,
    method: 'get',
    loading: false
  })
}

/**
 * 保存自定义的规格
 * @param category_id
 * @param data
 * @returns {*|Promise<unknown>}
 */
export const createSpec = (category_id, data) => {
  return request({
    url: `/seller/goods/categories/${category_id}/specs`,
    method: 'post',
    data
  })
}

/**
 * 保存自定义规格值
 * @param spec_id
 * @param data
 * @returns {*|Promise<unknown>}
 */
export const createSpecValue = (spec_id, data) => {
  return request({
    url: `/seller/goods/specs/${spec_id}/values`,
    method: 'post',
    data
  })
}

/**
 * 模拟睡眠
 * @param timer
 * @returns {Promise<unknown>}
 */
export const mockSleep = timer => new Promise(resolve => setTimeout(resolve, timer))

/**
 * 克隆数据
 * @param json
 * @returns {any}
 */
export const cloneJson = (json) => JSON.parse(JSON.stringify(json))

/**
 * 生成表格表单
 * @param selectedSpecs
 * @param params
 * @param skuList 商品的SKU数据，如果有的话，需要进行混入
 * @returns {{data: *, columns: *}}
 */
export const makeTableForm = (selectedSpecs, params, skuList) => {
  const tableHead = []
  // 插入参数的列
  params.forEach(param => tableHead.push(param))
  if (!selectedSpecs || selectedSpecs.length === 0) {
    return { data: [], columns: tableHead }
  }
  // 处理商品SKU数据
  const defaultSkus = cloneJson(skuList).map(sku => {
    if (Array.isArray(sku.spec_list)) {
      sku.spec_value_id = sku.spec_list.map(sv => sv.spec_value_id).join('|')
    }
    return sku
  })

  // 根据已选规格组合SKU
  const specs = selectedSpecs.map(sp => sp.spec_value_list)
  const skus = cartesianProduct(specs).map(item => {
    const sku = {}
    // 如果不是数组，说明规格只有一种
    if (!Array.isArray(item)) {
      sku.spec_value_id = item.spec_value_id
      sku.spec_list = [item].map(sv => ({
        ...sv,
        spec_type: sv.spec_image ? 1 : 0
      }))
    } else {
      sku.spec_value_id = item.map(sv => sv.spec_value_id).join('|')
      sku.spec_list = cloneJson(item).map(sv => ({
        ...sv,
        spec_type: sv.spec_image ? 1 : 0
      }))
    }
    // 写入已有SKU数据
    const defaultSku = defaultSkus.find(s => sku.spec_value_id.indexOf(s.spec_value_id) === 0) || {}
    if (defaultSku.sku_id) {
      sku.sku_id = defaultSku.sku_id
    }
    params.forEach(p => {
      sku[p.key] = defaultSku[p.key] !== null ? defaultSku[p.key] : p.value
    })
    return sku
  })

  // 利用笛卡尔乘积算法组合SKU
  function cartesianProduct(arr) {
    if (arr.length < 2) return arr[0] || []
    return [].reduce.call(arr, (col, set) => {
      let res = []
      col.forEach(c => {
        set.forEach(s => {
          let t = [].concat(Array.isArray(c) ? c : [c])
          t.push(s)
          res.push(t)
        })
      })
      return res
    })
  }
  return { data: cloneJson(skus), columns: cloneJson(tableHead) }
}

/**
 * 从规格源数据中取出已选规格
 * @param selectedSpecs 已选规格和规格值(只有ID)
 * @param specList 规格列表
 * @returns {*}
 */
export const getSelectedSpecsFormSpecList = (selectedSpecs, specList) => {
  // 遍历所有已选的规格
  // 遍历前先过滤掉没有选择规格，或规格值列表为空的
  const specs = cloneJson(selectedSpecs).filter(sp => {
    return !!sp.spec_id && sp.spec_value_list.filter(sv => !!sv.spec_value_id).length > 0
  })
  return specs.map(sp => {
    // 因为已选的规格只有spec_id，所以从specList中取源数据
    const spec = cloneJson(specList).find(item => item.spec_id === sp.spec_id)
    // 遍历规格值
    spec.spec_value_list = sp.spec_value_list.filter(sv => !!sv.spec_value_id).map(sv => {
      // 同理，取源数据
      const specVal = spec.value_list.find(item => item.spec_value_id === sv.spec_value_id)
      specVal.spec_image = sv.spec_image
      return specVal
    })
    return spec
  })
}

/**
 * 初始化已选规格信息
 * @param skus
 * @returns {{spec_value_list: *, spec_id: *}[]}
 */
export const initSelectedSpecs = (skus) => {
  let selectedSpecs = {}
  skus.forEach(sku => {
    if (!Array.isArray(sku.spec_list)) return
    sku.spec_list.forEach(spec => {
      const { spec_id, spec_value_id, spec_image } = spec
      const specVal = { spec_value_id, spec_image }
      if (!selectedSpecs[spec_id]) {
        selectedSpecs[spec_id] = {
          has_spec_image: !!spec_image,
          spec_value_list: [specVal]
        }
      } else if (!selectedSpecs[spec_id].spec_value_list.find(item => item.spec_value_id === spec_value_id)) {
        selectedSpecs[spec_id].spec_value_list.push(specVal)
      }
    })
  })
  return Object.keys(selectedSpecs).map(key => ({
    spec_id: key,
    has_spec_image: selectedSpecs[key].has_spec_image,
    spec_value_list: selectedSpecs[key].spec_value_list
  }))
}

/**
 * 计算SKU表单规则
 * @param skuForm
 * @param params
 * @returns {{skuList: *}}
 */
export const computedSkuRules = (skuForm, params) => {
  let { skuList, selectedSpecs } = cloneJson(skuForm)
  // SKU表单校验规则
  skuList = skuList.map(() => {
    const skuRule = {}
    // 遍历参数列表，生成参数规则
    params.forEach(p => {
      const rule = {}
      rule.required = !!p.required
      rule.trigger = p.trigger || 'blur'
      rule.message = p.message || ''
      // 如果有传入正则的情况，validator使用传入的正则校验
      if (p.reg) {
        rule.validator = (rule, value, callback) => {
          p.reg.test(value) ? callback() : callback(new Error(p.message))
        }
      }
      // 如果有传入自定义校验的情况，使用传入的validator校验
      if (typeof p.validator === 'function') rule.validator = p.validator
      skuRule[p.key] = rule
    })
    return skuRule
  })
  // 规格的校验规则
  selectedSpecs = selectedSpecs.map(sp => {
    let specRules = []
    if (Array.isArray(sp.spec_value_list)) {
      specRules = sp.spec_value_list.map((sv) => {
        return {
          spec_image: { required: sp.has_spec_image && sv.spec_value_id, trigger: 'change' },
          spec_id: { required: true, trigger: 'change' }
        }
      })
    }
    return { spec_value_list: specRules }
  })
  return { skuList, selectedSpecs }
}

/**
 * 规格维度是否发生改变
 * 如果有改变，移除sku_id
 * @param skus
 * @param rawSkus
 * @returns {boolean}
 */
export function specIsChanged(skus, rawSkus) {
  let changed = false
  skus.forEach(sku => {
    const rawSku = rawSkus.find(item => item.sku_id === sku.sku_id)
    if (!rawSku) return
    let raw_spec_value_id = ''
    if (Array.isArray(rawSku.spec_list)) {
      raw_spec_value_id = rawSku.spec_list.map(item => item.spec_value_id).join('|')
    }
    if (raw_spec_value_id === sku.spec_value_id) return
    changed = true
    delete sku.sku_id
  })
  return changed
}
